﻿//
// Copyright (c) 2019-2022 yanggaofeng
//
#include "YangHttp.h"
#include "httpserver.h"
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <netdb.h>
#include <unistd.h>
#include <string.h>
#include <stdarg.h>
#include <signal.h>
#include <sys/epoll.h>
#include <sys/timerfd.h>
#include "YangServerletManager.h"

#define RESPONSE "Hello, World!"

//YangConf *g_conf=NULL;
//struct http_server_s* poll_server=NULL;
int chunk_count = 0;
int request_target_is(struct http_request_s* request, char const * target) {
  http_string_t url = http_request_target(request);
  int len = strlen(target);
 // printf("\nurl==%s",url.buf);
  return len == url.len && memcmp(url.buf, target, url.len) == 0;
}
typedef struct {
  char* buf;
  struct http_response_s* response;
  int index;
} chunk_buf_t;


void chunk_cb(struct http_request_s* request) {
  chunk_count++;
  struct http_response_s* response = http_response_init();
  http_response_body(response, RESPONSE, sizeof(RESPONSE) - 1);
  if (chunk_count < 3) {
    http_respond_chunk(request, response, chunk_cb);
  } else {
    http_response_header(response, "Foo-Header", "bar");
    http_respond_chunk_end(request, response);
  }
}
void hs_server_init(http_server_t* serv) {
  serv->loop = epoll_create1(0);
  serv->timer_handler = hs_server_timer_cb;

  int tfd = timerfd_create(CLOCK_MONOTONIC, 0);
  struct itimerspec ts = {};
  ts.it_value.tv_sec = 1;
  ts.it_interval.tv_sec = 1;
  timerfd_settime(tfd, 0, &ts, NULL);

  struct epoll_event ev;
  ev.events = EPOLLIN | EPOLLET;
  ev.data.ptr = &serv->timer_handler;
  epoll_ctl(serv->loop, EPOLL_CTL_ADD, tfd, &ev);
  serv->timerfd = tfd;
}
http_server_t* http_server_init(int port, void (*handler)(http_request_t*)) {
  http_server_t* serv = (http_server_t*)malloc(sizeof(http_server_t));
  //assert(serv != NULL);
  serv->port = port;
  serv->memused = 0;
  serv->handler = hs_server_listen_cb;
  hs_server_init(serv);
  hs_generate_date_time(serv->date);
  serv->request_handler = handler;
  return serv;
}

void chunk_req_cb(struct http_request_s* request) {
  http_string_t str = http_request_chunk(request);
  chunk_buf_t* chunk_buffer = (chunk_buf_t*)http_request_userdata(request);
  if (str.len > 0) {
    memcpy(chunk_buffer->buf + chunk_buffer->index, str.buf, str.len);
    chunk_buffer->index += str.len;
    http_request_read_chunk(request, chunk_req_cb);
  } else {
    http_response_body(chunk_buffer->response, chunk_buffer->buf, chunk_buffer->index);
    http_respond(request, chunk_buffer->response);
    free(chunk_buffer->buf);
    free(chunk_buffer);
  }
}



void handle_request(struct http_request_s* request) {
  chunk_count = 0;
  //request->
  http_request_connection(request, HTTP_AUTOMATIC);
  struct http_response_s* response = http_response_init();
  http_response_status(response, 200);
  http_string_t method= http_request_method(request);
  //printf("method====%s\n",?"POST":"GET");
  if(request_target_is(request, "/yangmeeting/mthandle")&&memcmp(method.buf,"POST",4)==0){
	  http_string_t body = http_request_body(request);
	  YangServerletManager sm;
	  string s=sm.handle((char*)body.buf);
	 // printf("\nxml==%s\n",s.c_str());
	  http_response_header(response, "Content-Type", "text/plain");
	  http_response_body(response, s.c_str(), s.length());
	  return http_respond(request, response);
  }else  if (request_target_is(request, "/echo")) {
    http_string_t body = http_request_body(request);
    http_response_header(response, "Content-Type", "text/plain");
    http_response_body(response, body.buf, body.len);
  } else if (request_target_is(request, "/host")) {
    http_string_t ua = http_request_header(request, "Host");
    http_response_header(response, "Content-Type", "text/plain");
    http_response_body(response, ua.buf, ua.len);
  } else if (request_target_is(request, "/poll")) {
   // while (http_server_poll(poll_server) > 0);
    http_response_header(response, "Content-Type", "text/plain");
    http_response_body(response, RESPONSE, sizeof(RESPONSE) - 1);
  } else if (request_target_is(request, "/empty")) {
    // No Body
  } else if (request_target_is(request, "/chunked")) {
    http_response_header(response, "Content-Type", "text/plain");
    http_response_body(response, RESPONSE, sizeof(RESPONSE) - 1);
    http_respond_chunk(request, response, chunk_cb);
    return;
  } else if (request_target_is(request, "/chunked-req")) {
    chunk_buf_t* chunk_buffer = (chunk_buf_t*)calloc(1, sizeof(chunk_buf_t));
    chunk_buffer->buf = (char*)malloc(512 * 1024);
    chunk_buffer->response = response;
    http_request_set_userdata(request, chunk_buffer);
    http_request_read_chunk(request, chunk_req_cb);
    return;
  } else if (request_target_is(request, "/large")) {
    chunk_buf_t* chunk_buffer = (chunk_buf_t*)calloc(1, sizeof(chunk_buf_t));
    chunk_buffer->buf = (char*)malloc(25165824);
    chunk_buffer->response = response;
    http_request_set_userdata(request, chunk_buffer);
    http_request_read_chunk(request, chunk_req_cb);
    return;
  } else if (request_target_is(request, "/headers")) {
    int iter = 0, i = 0;
    http_string_t key, val;
    char buf[512];
    while (http_request_iterate_headers(request, &key, &val, &iter)) {
      i += snprintf(buf + i, 512 - i, "%.*s: %.*s\n", key.len, key.buf, val.len, val.buf);
    }
    http_response_header(response, "Content-Type", "text/plain");
    http_response_body(response, buf, i);
    return http_respond(request, response);
  } else {
    http_response_header(response, "Content-Type", "text/plain");
    http_response_body(response, RESPONSE, sizeof(RESPONSE) - 1);
  }
  http_respond(request, response);
}
YangHttp::YangHttp() {	//
	m_conf=NULL;
	//m_conf.init("yang_config.ini");
	//m_conf.initValue();
	//g_conf=&m_conf;
}
struct http_server_s* server=NULL;
YangHttp::~YangHttp() {
	m_conf=NULL;
	if(server) free(server);
	  server=NULL;
	//m_conf=
}


//void handle_sigterm(int signum) {
//  (void)signum;
//  if(server) free(server);
//  server=NULL;
  //if(poll_server) free(poll_server);
//  exit(0);
//}

void YangHttp::cycle(){
	 // signal(SIGTERM, handle_sigterm);
	  //g_sm.ym.initMysql(&m_conf);
	YangConnectionPool pool;
	pool.init(m_conf);
	  if(!server) server = http_server_init(m_conf->m_httpPort, handle_request);
	  //poll_server = http_server_init(8081, handle_request);
	 // http_server_listen_poll(poll_server);
	  http_server_listen(server);
}

void YangHttp::handle(){
	pthread_t th;
	 int ret = pthread_create( &th, NULL, run, this );
	// pthread_join();
	 pthread_detach(pthread_self());
}
void* YangHttp::run(void *arg){
	((YangHttp*)arg)->cycle();
	pthread_exit(0);
	return NULL;
}
